<template>
  <n-thing>
    <n-space vertical>
      <n-space>
        <n-switch v-model:value="toEdit"><template #unchecked>编辑看板</template></n-switch>
        看板名：<n-input
          v-model:value="taskBoardData.name"
          maxlength="70"
          type="text"
          :readonly="!toEdit"
        />
        所选领域：<n-select
          v-model:value="taskBoardData.chooseFields"
          placeholder="无回退选项"
          :consistent-menu-width="false"
          multiple
          :options="fieldTree.getFieldSelectOptions()"
          :disabled="!toEdit"
          :max-tag-count="1"
          filterable
        />
        <n-button
          @click="surfaceSetting.deleteTaskBoardData(props.index)"
          :disabled="!toEdit"
          type="error"
          dashed
          >删除看板</n-button
        >
        <n-switch
          v-model:value="toAdd"
          :disabled="toEdit"
          ><template #unchecked>添加任务</template></n-switch
        >
        <template v-if="toAdd && !toEdit">
          <n-select
            v-model:value="toAddFieldId"
            @update:value="toAddStageId = null"
            :options="fieldTree.getFieldSelectOptionsWithLimit(taskBoardData.chooseFields)"
            style="width: 200px"
            filterable
          />
          <n-select
            v-model:value="toAddStageId"
            :options="stageOptions"
            style="width: 200px"
            filterable
          />
          <n-select
            v-model:value="toAddType"
            :options="TaskData.getTypeOptions()"
            style="width: 100px"
          />
          <n-button
            @click="addNewOne()"
            type="primary"
            dashed
            >添加任务</n-button
          >
        </template>
      </n-space>
      <n-space>
        <n-space justify="space-between">
          <n-radio-group
            v-model:value="taskBoardData.radioOption"
            name="radiobuttongroup1"
          >
            <n-radio
              v-for="song in songs"
              :key="song.value"
              :value="song.value"
              :label="song.label"
            />
          </n-radio-group>
        </n-space>
        <n-space>
          任务个数：
          <template
            v-for="(data, index) in showCountTag"
            :key="index"
          >
            <n-tag type="success"> {{ data.name }}：{{ data.count }} </n-tag>
          </template>
        </n-space>
      </n-space>
    </n-space>
    <template v-if="taskBoardData.radioOption === '表格'">
      <n-layout
        has-sider
        style="height: 500px"
      >
        <n-layout-sider
          bordered
          show-trigger
          collapse-mode="width"
          :collapsed-width="64"
          :width="150"
          :native-scrollbar="false"
          style="max-height: 320px"
        >
          <n-menu
            v-model:value="taskBoardData.menuOption"
            :collapsed-width="64"
            :collapsed-icon-size="22"
            :options="TaskBoardData.getOptions()"
          />
        </n-layout-sider>
        <n-layout-content content-style="padding: 24px;">
          <n-data-table
            :columns="columns"
            :data="tableData"
            :pagination="{ pageSize: 15 }"
            :bordered="false"
            :row-props="rowProps"
            striped
          />
        </n-layout-content>
      </n-layout>
    </template>
    <template v-if="taskBoardData.radioOption === '日历'">
      <!--      {{events}}-->
      <TaskCalendar
        :events="events"
        :finish-events="finishEvents"
        :no-time-events="noTimeEvents"
        :key="calendarKey"
      ></TaskCalendar>
    </template>
  </n-thing>
  <n-dropdown
    placement="bottom-start"
    trigger="manual"
    :x="xRef"
    :y="yRef"
    :options="options"
    :show="showDropdownRef"
    :on-clickoutside="onClickoutside"
    @select="handleSelect"
  />
  <task-edit-drawer v-model="editSettings"></task-edit-drawer>
  <TaskMoveModal v-model="moveTask"></TaskMoveModal>
</template>

<script lang="ts" setup>
import TaskCalendar from "@/components/common/TaskCalendar.vue";
import TaskEditDrawer from "@/components/field/tasks/taskBtn/TaskEditDrawer.vue";
import TaskMoveModal from "@/components/field/tasks/taskBtn/TaskMoveModal.vue";
import { RemoveMethods } from "@/types/remove-methods";
import { TaskBoardData, TaskBoardList } from "@model/TaskBoardList";
import { TaskData } from "@model/TaskList";
import { FieldContentData } from "@model/fieldTree";
import { StageData, StageList } from "@model/stage";
import { SurfaceSetting } from "@model/surfaceSetting";
import UseCacheIdStatMap from "@pinias/UseCacheIdStatMap";
import UseFieldTree from "@pinias/UseFieldTree";
import UseStage from "@pinias/UseStage";
import UseSurfaceSetting from "@pinias/UseSurfaceSetting";
import UseTask from "@pinias/UseTask";
import pinia from "@pinias/pinia";
import { getstartOfDay, timestampToDateTime } from "@utils/DateUtils";
import { NButton, NDataTable, NLayout, NLayoutContent, NLayoutSider, NMenu, NSpace, useMessage } from "naive-ui";
import { ref, watch, h, reactive, onMounted } from "vue";

// 全局数据
const { getSurfaceSetting } = UseSurfaceSetting(pinia);
const surfaceSetting: SurfaceSetting = getSurfaceSetting();
const { getFieldTree } = UseFieldTree(pinia);
const fieldTree = getFieldTree();
const { getStageList } = UseStage(pinia);
const stageList: StageList = getStageList();
const { getTaskList } = UseTask(pinia);
const taskList = getTaskList();
const { getCacheIdStatMap } = UseCacheIdStatMap(pinia);
const cacheIdStatMap = getCacheIdStatMap();

// 当前页面数据
const props = defineProps(["index"]);
const taskBoardData = surfaceSetting.getTaskBoardDataById(props.index);
const toEdit = ref(false);
const editSettings = reactive<{
  toEdit: boolean;
  toDelete: boolean;
  toDealRowId: number | undefined;
  type: number;
  state: string | undefined;
  stageId: number;
}>({
  toEdit: false,
  toDelete: false,
  toDealRowId: undefined,
  type: 1,
  state: undefined,
  stageId: 0,
});
const moveTask = reactive<{
  toMove: boolean;
  taskId: number;
  type: number;
  state: string;
  originalStageId: number;
  toSaveStageId: number | null;
  toSaveField: number | undefined;
}>({ toMove: false, taskId: 0, type: 0, state: "", originalStageId: 0, toSaveStageId: 0, toSaveField: 0 });
class RowData {
  id: number;
  name: string;
  desc: string;
  stageName: string;
  stageId: number;
  fieldName: string;
  deadLine: string | null;
  mentionTime: string;
  takeTime: string;
  type: string;
  finishTime: number;
  failTime: number;
  constructor(data: RemoveMethods<RowData>) {
    Object.assign(this, data);
  }
  static getNullModel() {
    return new RowData({
      id: 0,
      name: "",
      desc: "",
      stageName: "",
      stageId: 0,
      fieldName: "",
      deadLine: "",
      mentionTime: "",
      takeTime: "",
      type: "",
      finishTime: 0,
      failTime: 0,
    });
  }
}
// 获取表格数据
const getShowCountTag = (result: Map<string, Array<RowData>>) => {
  // console.log(result,"+++++++++++++++++++++++")
  const show = new Array<{ name: string; count: number }>();
  for (const allResultElement of result.keys()) {
    let count = 0;
    // console.log(allResultElement,"+++++++++++++++++++++++")
    const i = result.get(allResultElement);
    if (i !== undefined) {
      count = i.length;
    }
    show.push({ name: allResultElement, count: count });
  }
  return show;
};
const putTaskData = async (
  taskIds: Array<number> | undefined,
  key: string,
  result: Map<string, Array<RowData>>,
  stageData: StageData,
  fieldData: FieldContentData,
) => {
  if (taskIds !== undefined) {
    const timeStamp = new Date().getTime();
    for (let k = 0; k < taskIds.length; k++) {
      const taskData = taskList.getTaskDataById(taskIds[k]);
      if (taskData !== undefined) {
        const data = new RowData({
          id: taskData.id,
          name: taskData.name,
          desc: taskData.desc,
          stageName: stageData.name,
          stageId: stageData.id,
          fieldName: fieldData.topic,
          deadLine: timestampToDateTime(taskData.timeMentionModal.deadLine),
          mentionTime: timestampToDateTime(taskData.mentionTime),
          takeTime: await cacheIdStatMap.getTakeTime(taskData.id, []),
          type: TaskData.getTypeStr(taskData.type),
          finishTime: taskData.finishTime,
          failTime: taskData.failTime,
        });
        if (key === "进行中") {
          // console.log(data.deadLine, taskData.mentionTime);
          if (
            taskData.timeMentionModal.deadLine === null ||
            taskData.mentionTime === undefined ||
            taskData.mentionTime < 10
          )
            result.get("未指定日期")?.push(data);
          else if (taskData.timeMentionModal.deadLine <= timeStamp) result.get("过期")?.push(data);
          else if (taskData.mentionTime > timeStamp) result.get("未提醒")?.push(data);
          else if (taskData.mentionTime <= timeStamp) result.get("需处理")?.push(data);
        } else {
          result.get(key)?.push(data);
        }
      }
    }
  }
};
const getAllResults = async () => {
  const result = new Map<string, Array<RowData>>();
  for (const option of TaskBoardData.getOptions()) {
    result.set(option.key, []);
  }
  const chooseFields = taskBoardData.chooseFields;
  for (let i = 0; i < chooseFields.length; i++) {
    const fieldId = chooseFields[i];
    const fieldData = fieldTree.getFieldDataById(fieldId);
    if (fieldData !== undefined) {
      const stageIds = fieldData.stageIds.onGonging;
      if (stageIds !== undefined) {
        for (let j = 0; j < stageIds.length; j++) {
          const stageData = stageList.getStageDataById(stageIds[j]);
          if (stageData !== undefined) {
            await putTaskData(stageData.task.TaskBased.onGonging, "进行中", result, stageData, fieldData);
            await putTaskData(stageData.task.ClockBased.onGonging, "进行中", result, stageData, fieldData);
            await putTaskData(stageData.task.TaskBased.stopping, "未开始", result, stageData, fieldData);
            await putTaskData(stageData.task.ClockBased.stopping, "未开始", result, stageData, fieldData);
            await putTaskData(stageData.task.TaskBased.finished, "已结束", result, stageData, fieldData);
            await putTaskData(stageData.task.ClockBased.finished, "已结束", result, stageData, fieldData);
          }
        }
      }
    }
  }
  showCountTag.value = getShowCountTag(result);
  return result;
};
let allResult = new Map<string, Array<RowData>>();
// 渲染表格数据
const getTableData = () => {
  return allResult.get(taskBoardData.menuOption);
};
const tableData = ref(getTableData());
const showCountTag = ref(new Array<{ name: string; count: number }>());

const watchResults = async () => {
  allResult = await getAllResults();
  // console.log(allResult)
  tableData.value = getTableData();
  getEvents();
  calendarKey.value = new Date().valueOf();
};
watch(taskBoardData, watchResults);
onMounted(watchResults);
// 获取行头
const createColumns = () => {
  return [
    // {
    //   title: "id",
    //   key: "id",
    //   width: 100,
    // },
    {
      title: "名字",
      key: "name",
      // width: 200,
    },
    {
      title: "描述",
      key: "desc",
      width: 70,
      ellipsis: {
        tooltip: true,
      },
    },
    {
      title: "阶段",
      key: "stageName",
    },
    {
      title: "领域",
      key: "fieldName",
    },
    {
      title: "类型",
      key: "type",
    },
    {
      title: "截止日期",
      key: "deadLine",
    },
    {
      title: "提醒时间",
      key: "mentionTime",
    },
    {
      title: "所花时间",
      key: "takeTime",
    },
    {
      title: "打卡次数",
      key: "finishTime",
    },
    {
      title: "失败次数",
      key: "failTime",
    },
    {
      title: "Action",
      key: "actions",
      render(row: RowData) {
        const btns = [];
        btns.push(
          h(
            NButton,
            {
              strong: true,
              tertiary: true,
              size: "small",
              id: "handle-drag",
              onClick: () => play(row),
            },
            { default: () => "计时" },
          ),
        );
        return btns;
      },
    },
  ];
};
const message = useMessage();
const columns = createColumns();

// 添加任务逻辑
const toAdd = ref(false);
const stageOptions = ref<Array<{ label: string; value: number }>>([]);
const toAddStageId = ref<number | null>(null);
const toAddFieldId = ref<number | null>(null);
const toAddType = ref<null | number>(null);
watch(toAddFieldId, () => {
  const field = fieldTree.getFieldDataById(toAddFieldId.value);
  stageOptions.value = stageList.getStageSelectOptions(field);
});
watch(toEdit, () => {
  if (toEdit.value) {
    toAdd.value = false;
  }
});
watch(toAdd, () => {
  if (toAdd.value) {
    toAddStageId.value = null;
    toAddFieldId.value = null;
    toAddType.value = null;
  }
});
const addNewOne = () => {
  if (toAddStageId.value !== null && toAddType.value !== null) {
    console.log(editSettings);
    editSettings.stageId = toAddStageId.value;
    editSettings.toDealRowId = undefined;
    editSettings.type = toAddType.value;
    editSettings.toEdit = true;
  } else message.error("选择有误");
};

// 右键菜单
let chooseRow = RowData.getNullModel();
const rowProps = (row: RowData) => {
  return {
    onContextmenu: (e: MouseEvent) => {
      // message.info(JSON.stringify(row, null, 2));
      showDropdownRef.value = true;
      xRef.value = e.clientX;
      yRef.value = e.clientY;
      // console.log('rowProps',row)
      editSettings.toDealRowId = row.id;
      chooseRow = row;
    },
  };
};
const options = [
  {
    label: "编辑",
    key: "edit",
  },
  {
    label: "移动",
    key: "move",
  },
  {
    label: () => h("span", { style: { color: "red" } }, "完成"),
    key: "finish",
  },
  {
    label: () => h("span", { style: { color: "red" } }, "失败"),
    key: "fail",
  },
];
const showDropdownRef = ref(false);
const xRef = ref(0);
const yRef = ref(0);
const onClickoutside = () => {
  showDropdownRef.value = false;
};
const handleSelect = (key: string, node: string) => {
  console.log(key, node);
  showDropdownRef.value = false;
  if (key == "edit") {
    edit(chooseRow);
  }
  if (key == "move") {
    move(chooseRow);
  }
  if (key == "finish" || key == "fail") {
    if (taskBoardData.menuOption !== "已结束" && taskBoardData.menuOption !== "未开始") {
      finish(chooseRow, key);
    } else message.error("已结束和未开始的不可完成");
  }
};
const move = (row: RowData) => {
  if (editSettings.toDealRowId !== undefined) {
    moveTask.type = TaskData.getTypeNum(row.type);
    moveTask.originalStageId = row.stageId;
    moveTask.toSaveStageId = row.stageId;
    moveTask.state = TaskBoardData.getOptionKey(taskBoardData.menuOption);
    moveTask.taskId = row.id;
    moveTask.toMove = true;
  }
};
const edit = (row: RowData) => {
  // message.info(`Play ${row.title}`);
  editSettings.stageId = row.stageId;
  editSettings.type = TaskData.getTypeNum(row.type);
  editSettings.toDealRowId = row.id;
  editSettings.state = TaskBoardData.getOptionKey(taskBoardData.menuOption);
  editSettings.toEdit = true;
};
const play = (row: RowData) => {
  // message.info(`Play ${row.title}`);
  if (TaskBoardList.beginRecord(surfaceSetting.taskBoardList, row.id, 1)) message.success("开始计时");
  else message.error("存在计时的任务");
};
const finish = (row: RowData, key: string) => {
  taskList.finishTask(
    row.id,
    TaskData.getTypeNum(row.type),
    TaskBoardData.getOptionKey(taskBoardData.menuOption),
    stageList,
    surfaceSetting,
    key,
  );
  taskBoardData.key = new Date().getTime();
};

// 单选选项
const calendarKey = ref(10);
// const value = ref(taskBoardData.radioOption!== undefined?taskBoardData.radioOption:"表格");
const songs = [
  {
    value: "表格",
    label: "表格",
  },
  {
    value: "日历",
    label: "日历",
  },
].map(s => {
  s.value = s.value.toLowerCase();
  return s;
});
//  { title: 'event 1', start: '2023-08-25 14:22:00',color: 'red',description: 'description for Long Event', },
let events = new Array<{ title: string; start: string; end: string; color: string; description: string }>();
let finishEvents = new Array<{ title: string; start: string; end: string; color: string; description: string }>();
let noTimeEvents = new Array<{ title: string; start: string; end: string; color: string; description: string }>();
const getEvents = () => {
  if (taskBoardData.radioOption === "日历") {
    events = [];
    finishEvents = [];
    noTimeEvents = [];
    let results = allResult.get("未提醒");
    if (results !== undefined && results.length > 0) {
      for (const rowDatum of results) {
        putEvent(rowDatum, false, "green");
      }
    }
    results = allResult.get("过期");
    if (results !== undefined && results.length > 0) {
      for (const rowDatum of results) {
        putEvent(rowDatum, false, "red");
      }
    }
    results = allResult.get("需处理");
    if (results !== undefined && results.length > 0) {
      for (const rowDatum of results) {
        putEvent(rowDatum, false, "yellow");
      }
    }
    results = allResult.get("未开始");
    if (results !== undefined && results.length > 0) {
      for (const rowDatum of results) {
        putEvent(rowDatum, false, "purple");
      }
    }
    results = allResult.get("未指定日期");
    if (results !== undefined && results.length > 0) {
      for (const rowDatum of results) {
        putEvent(rowDatum, false, "black");
      }
    }
    results = allResult.get("已结束");
    if (results !== undefined && results.length > 0) {
      for (const rowDatum of results) {
        putEvent(rowDatum, true, "gray");
      }
    }
  }
};
const putEvent = (rowDatum: RowData, finish: boolean, color: string) => {
  if (rowDatum !== undefined) {
    if (rowDatum.deadLine !== null && rowDatum.deadLine.length > 0) {
      const e = {
        title: rowDatum.name,
        start: rowDatum.deadLine,
        end: rowDatum.deadLine,
        color: color,
        description: rowDatum.desc,
      };
      if (finish) finishEvents.push(e);
      else events.push(e);
    } else {
      if (!finish) {
        const ddl = timestampToDateTime(getstartOfDay(new Date().valueOf()));
        const e = {
          title: rowDatum.name,
          start: ddl,
          end: ddl,
          color: "black",
          description: rowDatum.desc,
        };
        noTimeEvents.push(e);
      }
    }
  }
};
// watch(value, () => {
//   taskBoardData.radioOption = value.value;
//   // getEvents();
// });
</script>
